package com.github.ylt.utils;

import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class XmlUtils {
    private DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    private DocumentBuilder builder;
    private XmlUtils() {
        try {
            builder= factory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

    private static final class InstanceHolder {
        private static final XmlUtils INSTANCE = new XmlUtils();
    }

    public static XmlUtils getInstance() {
        return InstanceHolder.INSTANCE;
    }

    public Map<String,Object> parse(String xml) throws IOException, DocumentException {
        Map<String,Object> result = new HashMap<>();
        SAXReader reader = new SAXReader();
        Document document = reader.read(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
        Element rootElement = document.getRootElement();
        Iterator<Element> elementIterator = rootElement.elementIterator("Body");
        while (elementIterator.hasNext()){
            Element next = elementIterator.next();
            Iterator<Element> elementIterator1 = next.elementIterator();
            while (elementIterator1.hasNext()){
                Element next1 = elementIterator1.next();
                Iterator<Element> elementIterator2 = next1.elementIterator();
                while (elementIterator2.hasNext()){
                    Element next2 = elementIterator2.next();
                    result.put(next2.getName(), next2.getText());
                }

            }

        }
        return result;
    }

    public Map<String,Object> parseMateData(String xml){
        Map<String,Object> result = new HashMap<>();
        SAXReader reader = new SAXReader();
        Document document = null;
        try {
            document = reader.read(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
            Element rootElement = document.getRootElement();
            rootElement.elementIterator("item").forEachRemaining(item->result.put(item.getName(), item.getText()));
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    public String responseXml(Map<String,Object> map,String action,String nameSpace){
        return buildingXml(map,action,nameSpace,true);
    }

    public String requestXml(Map<String,Object> map,String action,String nameSpace){
        return buildingXml(map,action,nameSpace,false);
    }

    private String buildingXml(Map<String,Object> map,String action,String nameSpace,boolean isResponse){
        Document document = DocumentHelper.createDocument();
        document.setXMLEncoding("utf-8");
        Element rootElement = document.addElement("s:Envelope");
        rootElement.addNamespace("s","http://schemas.xmlsoap.org/soap/envelope/");
        rootElement.addAttribute("s:encodingStyle","http://schemas.xmlsoap.org/soap/encoding/");
        Element body =  DocumentHelper.createDocument().addElement("s:Body");
        Element element = null;
        if(isResponse){
            element =  DocumentHelper.createDocument().addElement("u:"+action+"Response");
        }else{
            element =  DocumentHelper.createDocument().addElement("u:"+action);
        }
        element.addNamespace("u",nameSpace);
        body.add(element);
        for(Map.Entry<String,Object> entry:map.entrySet()){
            Element element1 =  DocumentHelper.createDocument().addElement(entry.getKey());
            element1.setData(entry.getValue());
            element.add(element1);
        }
        rootElement.add(body);
        document.setRootElement(rootElement);
        return document.asXML();
    }
}
